package services

import (
	"GOPAAS/configs/config"
	"GOPAAS/internal/app/global"
	"GOPAAS/internal/app/model"
	"GOPAAS/internal/utils"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"net/url"
	"os"
	"strconv"
)

var word_type = []string{"application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"}
var ppt_type = []string{"application/vnd.openxmlformats-officedocument.presentationml.document"}
var excel_type = []string{"application/vnd.openxmlformats-officedocument.spreadsheetml.document"}
var pdf_type = []string{"application/pdf"}
var zip_type = []string{"application/zip"}

type DocumentService struct {
	model.DocumentsDocument
}

func GetDocumentService(aid int64) *DocumentService {
	db = getDB()
	var document model.DocumentsDocument
	if aid > 0 {
		db.First(&document, aid)
	}
	return &DocumentService{document}
}

type DocumentsFolderService struct {
	model.DocumentsFolder
}

func GetDocumentsFolderService(fid int64) *DocumentsFolderService {
	db = getDB()
	var documents_folder model.DocumentsFolder
	if fid > 0 {
		db.First(&documents_folder, fid)
	}
	return &DocumentsFolderService{documents_folder}
}

// MyFolders 我的目录
func MyFolders(user_id int64, company_id int64, parent_id int64) []global.FolderTree {
	db = getDB()
	lang, _ := c.Get("lang")
	user_service := GetUserService(user_id)
	user_info, _ := user_service.GetUserInfo()
	//已设置文件夹权限的
	var read_folders []int64
	db.Model(model.DocumentsFolderReadGroups{}).Where("res_groups_id in ?", user_info.Groups).Pluck("documents_folder_id", &read_folders)
	var write_folders []int64
	db.Model(model.DocumentsFolderResGroupsRel{}).Where("res_groups_id in ?", user_info.Groups).Pluck("documents_folder_id", &write_folders)
	var user_folders []int64
	db.Model(model.DocumentsFolderPerm{}).Where("(perm_read = ? or perm_write=?) and user_id=?", true, true, user_id).Pluck("folder_id", &user_folders)
	all_folder_ids := append(read_folders, write_folders...)
	all_folder_ids = append(all_folder_ids, user_folders...)
	//所有设置权限的文件夹
	//var perm_folders []int64
	//var perm_read_folders, perm_write_folders, perm_user_folders []int64
	//db.Model(model.DocumentsFolderReadGroups{}).Pluck("documents_folder_id", &perm_read_folders)
	//db.Model(model.DocumentsFolderResGroupsRel{}).Pluck("documents_folder_id", &perm_write_folders)
	//db.Model(model.DocumentsFolderPerm{}).Pluck("folder_id", &perm_user_folders)
	//perm_folders = append(perm_folders, perm_read_folders...)
	//perm_folders = append(perm_folders, perm_write_folders...)
	//perm_folders = append(perm_folders, perm_user_folders...)

	//q := db.Where("id in ? or id not in ? or create_uid =?", all_folder_ids, perm_folders, user_id)
	q := db.Where("id in ? or create_uid =?", all_folder_ids, user_id)
	if parent_id > 0 {
		q.Where("parent_path like ?", strconv.Itoa(int(parent_id))+"/%")
	}
	var folders []model.DocumentsFolder
	db.Where("company_id = ? or company_id is null", company_id).Where(q).Order("id").Find(&folders)
	res := folderTrees(folders, lang.(string))
	return res
}

// folderTrees 文件夹树
func folderTrees(data []model.DocumentsFolder, lang string) []global.FolderTree {
	var res []global.FolderTree
	for _, v := range data {
		res = append(res, global.FolderTree{
			Id:       v.Id,
			Name:     utils.GetJsonName(v.Name, lang),
			ParentId: v.ParentFolderId.Int64,
			Data: map[string]string{
				"create_date": v.CreateDate.Format("2006-01-02 15:04:05"),
				"date_beauty": utils.BeautifyDate(v.CreateDate),
			},
		})
	}
	return utils.GenerateTree(res, 0)
}

type DocumentItem struct {
	Id           int64  `json:"id"`
	AttachmentId int64  `json:"attachment_id"`
	Icon         string `json:"icon"`
	CreateDate   string `json:"create_date"`
	DateBeauty   string `json:"date_beauty"`
	Name         string `json:"name"`
	Url          string `json:"url"`
	PreviewUrl   string `json:"preview_url"`
	Mimetype     string `json:"mimetype"`
	FolderId     int64  `json:"folder_id"`
	FolderIdName string `json:"folder_id_name"`
}
type JoinModel struct {
	model.DocumentsDocument
	Mimetype string
}

// MyDocuments 我的文档
func MyDocuments(c *gin.Context, user_id int64, folder_id int64, tab string, search string, d_type string, ids []int64, page int, limit int) (res []DocumentItem, err error) {
	db = getDB()
	lang, _ := c.Get("lang")
	user_service := GetUserService(user_id)
	//文档权限
	var mime_documents_ids []int64
	//db.Model(&model.DocumentsDocumentResUsersRel{}).Pluck("documents_document_id", &perm_documents_ids)
	db.Model(&model.DocumentsDocumentPerm{}).Where("user_id = ? and (perm_read = true or perm_write = true)", user_id).Pluck("document_id", &mime_documents_ids)
	perm_w := db.Where("documents_document.id in ? or owner_id =?", mime_documents_ids, user_id)
	q := db.Model(&model.DocumentsDocument{}).Joins("left join ir_attachment on documents_document.attachment_id=ir_attachment.id").Where(perm_w).Where("folder_id=?", folder_id)
	if len(ids) > 0 {
		q.Where("documents_document.id in ?", ids)
	}
	if d_type != "" {
		switch d_type {
		case "word":
			q.Where("mimetype in ?", word_type)
		case "ppt":
			q.Where("mimetype in ?", ppt_type)
		case "excel":
			q.Where("mimetype in ?", excel_type)
		case "pdf":
			q.Where("mimetype in ?", pdf_type)
		case "images":
			q.Where("mimetype like ?", "images/%")
		case "video":
			q.Where("mimetype like ?", "video/%")
		case "zip":
			q.Where("mimetype in ?", zip_type)
		case "other":
			all_type := append(word_type, ppt_type...)
			all_type = append(all_type, excel_type...)
			all_type = append(all_type, pdf_type...)
			all_type = append(all_type, zip_type...)
			q.Where("mimetype not in ?", all_type)
			q.Where("mimetype not like ?", "images/%")
			q.Where("mimetype not like ?", "video/%")
		}
	}
	if search != "" {
		q.Where("name like ?", "%"+search+"%")
	}
	if tab == "mine" {
		q.Where("user_id=?", user_id)
	} else if tab == "recent" {
		q.Order("document_document.write_date desc")
	} else if tab == "share" {
		var res_ids []int64
		db.Model(&model.MailFollowers{}).Where("res_model=? and partner_id = ?", "documents.document", user_service.PartnerId).Pluck("res_id", &res_ids)
		q.Where("documents_document.id in ?", res_ids)
	}
	var docs []JoinModel
	offset := (page - 1) * limit
	q.Preload("Folder").Offset(offset).Limit(limit).Select("documents_document.*", "ir_attachment.mimetype").Find(&docs)
	for _, v := range docs {
		attach_service := GetAttachService(v.AttachmentId)
		var url = v.Url.String
		if v.Type == "binary" {
			url = "http://" + config.Conf.Host + GetAttach("documents.document", v.Id, attach_service.Checksum)
		}
		res = append(res, DocumentItem{
			Id:           v.Id,
			AttachmentId: v.AttachmentId,
			Icon:         attach_service.GetIcon(),
			CreateDate:   v.CreateDate.Format("2006-01-02 15:04:05"),
			DateBeauty:   utils.BeautifyDate(utils.ForceCorrectTime(v.CreateDate)),
			Name:         v.Name,
			PreviewUrl:   GetPreviewUrl(url, v.Name),
			Url:          url,
			Mimetype:     v.Mimetype,
			FolderId:     v.FolderId,
			FolderIdName: utils.GetJsonName(v.Folder.Name, lang.(string)),
		})
	}
	return
}
func GetPreviewUrl(originUrl string, file_name string) string {
	var previewUrl = originUrl + "&fullfilename=" + file_name
	return fmt.Sprintf("%s/onlinePreview?url=%s", config.Conf.PreviewPath, url.QueryEscape(utils.Base64([]byte(previewUrl))))
}

// Remove 移除文件夹
func (f *DocumentsFolderService) Remove(user_id int64) error {
	db = getDB()
	var res model.DocumentsFolder
	var res1 model.DocumentsDocument
	db.Where("parent_folder_id=?", f.Id).First(&res)
	db.Where("folder_id=?", f.Id).First(&res1)
	if res.Id > 0 || res1.Id > 0 {
		return errors.New("该文件夹不是空文件夹！请先删除文件夹下内容！")
	}
	if f.CreateUid != user_id {
		return errors.New("删除失败，你不能删除该文件夹")
	}
	err := db.Delete(f.DocumentsFolder).Error
	return err
}

// Add 添加文件夹
func (f *DocumentsFolderService) Add(c *gin.Context, user_id int64, company_id int64, name string, description string) (folder_id int64, err error) {
	var description_c = utils.NullStringValue(description)
	lang, _ := c.Get("lang")
	description_c.String = utils.SetJsonName(description_c.String, lang.(string))
	var folder = model.DocumentsFolder{
		CompanyId:      utils.NullInt64Value(company_id),
		ParentFolderId: utils.NullInt64Value(f.Id),
		Name:           utils.SetJsonName(name, lang.(string)),
		Description:    description_c,
		Sequence:       10,
		ResCommon: model.ResCommon{
			CreateUid: user_id,
			WriteUid:  user_id,
		},
	}
	db = getDB()
	err = db.Create(&folder).Error
	folder_id = folder.Id
	return
}

// Remove 移除文件
func (d *DocumentService) Remove(user_id int64) (err error) {
	if d.CreateUid != user_id {
		return errors.New("删除失败，你不能删除该文件")
	}
	db = getDB()
	var attachment model.IrAttachment
	db.First(&attachment, d.AttachmentId)
	if attachment.Id > 0 {
		db.Delete(&attachment)
		before_file := config.Conf.DataDir + "/" + attachment.StoreFname
		os.Remove(before_file)
	}
	err = db.Delete(d.DocumentsDocument).Error
	return
}

// Rename 重命名文件
func (d *DocumentService) Rename(user_id int64, name string) (err error) {
	if d.CreateUid != user_id {
		return errors.New("删除失败，你不能删除该文件")
	}
	db = getDB()
	var attachment model.IrAttachment
	db.First(&attachment, d.AttachmentId)
	if attachment.Id > 0 {
		attachment.Name = name
		attachment.WriteUid = user_id
		db.Select("Name").Save(&attachment)
	}
	d.Name = name
	d.WriteUid = user_id
	err = db.Select("Name").Save(d.DocumentsDocument).Error
	return
}

// Share 分享文件
func (d *DocumentService) Share(user_id int64, code string) (share_url string, err error) {
	return ShareDocument(user_id, d.FolderId, []int64{d.Id}, code)
}

// Perm 文档权限
func (d *DocumentService) Perm(user_id int64) (result []string) {
	db = getDB()
	if d.OwnerId == user_id {
		result = append(result, "write", "read")
		return
	}
	var perm model.DocumentsDocumentPerm
	db.Model(&model.DocumentsDocumentPerm{}).Where("user_id = ? and document_id=?", user_id, d.Id).First(&perm)
	if perm.PermRead {
		result = append(result, "read")
		return
	}
	if perm.PermWrite {
		result = append(result, "write")
		return
	}
	return
}

// Rename 重命名文件夹
func (f *DocumentsFolderService) Rename(c *gin.Context, user_id int64, name string) (err error) {
	db = getDB()
	lang, _ := c.Get("lang")
	f.Name = utils.SetJsonName(name, lang.(string))
	f.WriteUid = user_id
	err = db.Select("Name").Save(&f.DocumentsFolder).Error
	return
}

// Perm 文件夹权限
func (f *DocumentsFolderService) Perm(user_id int64) (result []string) {
	db = getDB()
	user_service := GetUserService(user_id)
	user_info, _ := user_service.GetUserInfo()
	if f.CreateUid == user_id {
		result = append(result, "write", "read")
		return
	}
	var perm model.DocumentsFolderPerm
	db.Model(&model.DocumentsFolderPerm{}).Where("user_id = ? and folder_id=?", user_id, f.Id).First(&perm)
	if perm.PermRead {
		result = append(result, "read")
	} else {
		var read_perm model.DocumentsFolderReadGroups
		res := db.Model(model.DocumentsFolderReadGroups{}).Where("documents_folder_id=? and res_groups_id in ?", f.Id, user_info.Groups).First(&read_perm)
		if res.RowsAffected > 0 {
			result = append(result, "read")
		}
	}
	if perm.PermWrite {
		result = append(result, "write")
	} else {
		var read_perm model.DocumentsFolderResGroupsRel
		res := db.Model(model.DocumentsFolderResGroupsRel{}).Where("documents_folder_id=? and res_groups_id in ?", f.Id, user_info.Groups).First(&read_perm)
		if res.RowsAffected > 0 {
			result = append(result, "write")
		}
	}
	return
}

// Share 分享文件夹
func (f *DocumentsFolderService) Share(user_id int64, code string) (share_url string, err error) {
	return ShareDocument(user_id, f.Id, []int64{}, code)
}

// ShareDocument 添加分享文档数据
func ShareDocument(user_id int64, folder_id int64, document_ids []int64, code string) (share_url string, err error) {
	db = getDB()
	var share = model.DocumentsShare{
		AliasId:                       3,
		FolderId:                      folder_id,
		OwnerId:                       user_id,
		AccessToken:                   utils.GetToken(),
		Type:                          "ids",
		Name:                          utils.NullStringValue(code),
		Domain:                        utils.NullStringValue(fmt.Sprintf("[['folder_id', 'child_of', %d]]", folder_id)),
		Action:                        "download",
		ActivityDateDeadlineRangeType: "days",
		ResCommon: model.ResCommon{
			CreateUid: user_id,
			WriteUid:  user_id,
		},
	}
	err = db.Select("AliasId", "FolderId", "OwnerId", "AccessToken", "Type", "Name", "Domain", "Action", "ActivityDateDeadlineRangeType", "CreateUid", "WriteUid").Create(&share).Error
	if err != nil {
		return
	}
	if len(document_ids) > 0 {
		var batch_insert = []model.DocumentsDocumentDocumentsShareRel{}
		for _, v := range document_ids {
			batch_insert = append(batch_insert, model.DocumentsDocumentDocumentsShareRel{
				DocumentsShareId:    share.Id,
				DocumentsDocumentId: v,
			})
		}
		err = db.Create(&batch_insert).Error
		if err != nil {
			return
		}
	}
	share_url = fmt.Sprintf("/h5/document.share/%d/%s", share.Id, share.AccessToken)
	return
}

type DocumentsShareService struct {
	model.DocumentsShare
}

func GetDocumentsShareService(sid int64) *DocumentsShareService {
	db = getDB()
	var documents_share model.DocumentsShare
	if sid > 0 {
		db.First(&documents_share, sid)
	}
	return &DocumentsShareService{documents_share}
}

func (ds *DocumentsShareService) GetShareDocumentIds() []int64 {
	db = getDB()
	var shar_documents model.DocumentsDocumentDocumentsShareRel
	var document_ids []int64
	db.Model(&shar_documents).Where("documents_share_id=?", ds.Id).Pluck("documents_document_id", &document_ids)
	return document_ids
}
